package com.wenx.v3auth.interceptor;

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.HashMap;
import java.util.Map;

/**
 * OAuth2 Token端点拦截器
 * 
 * <p>拦截并记录OAuth2 Token端点的所有请求，包括：</p>
 * <ul>
 *   <li>授权码换取访问令牌 (/oauth2/token)</li>
 *   <li>刷新令牌请求</li>
 *   <li>客户端凭证请求</li>
 *   <li>设备授权请求</li>
 * </ul>
 * 
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Component
public class V3TokenEndpointInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, 
                           @NonNull HttpServletResponse response, 
                           @NonNull Object handler) {
        
        if (isOAuth2Endpoint(request.getRequestURI())) {
            logTokenRequest(request);
        }
        return true;
    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, 
                              @NonNull HttpServletResponse response, 
                              @NonNull Object handler, 
                              Exception ex) {
        
        if (isOAuth2Endpoint(request.getRequestURI())) {
            logTokenResponse(request, response, ex);
        }
    }

    /**
     * 判断是否为OAuth2端点
     */
    private boolean isOAuth2Endpoint(String requestURI) {
        return requestURI.startsWith("/oauth2/") || 
               requestURI.startsWith("/connect/") ||
               requestURI.equals("/userinfo");
    }

    /**
     * 记录Token请求
     */
    private void logTokenRequest(HttpServletRequest request) {
        Map<String, Object> logData = Map.of(
            "action", "TOKEN_REQUEST",
            "method", request.getMethod(),
            "uri", request.getRequestURI(),
            "remoteAddr", getClientIpAddress(request),
            "grantType", request.getParameter("grant_type"),
            "clientId", request.getParameter("client_id")
        );
        
        log.info("[OAuth2Token请求] {}", JSON.toJSONString(logData));
    }

    /**
     * 记录Token响应
     */
    private void logTokenResponse(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("action", "TOKEN_RESPONSE");
        logData.put("uri", request.getRequestURI());
        logData.put("status", response.getStatus());
        logData.put("remoteAddr", getClientIpAddress(request));
        
        if (ex != null) {
            logData.put("error", ex.getMessage());
        }
        
        if (response.getStatus() >= 400) {
            log.warn("[OAuth2Token响应] {}", JSON.toJSONString(logData));
        } else {
            log.info("[OAuth2Token响应] {}", JSON.toJSONString(logData));
        }
    }

    /**
     * 获取客户端真实IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (StringUtils.hasText(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (StringUtils.hasText(xRealIp)) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }
} 